#include "Restaurant.h"
#include <string>
#include <iostream>
using namespace std;

//Default constructor
Restaurant::Restaurant(){
	numOfGuests = 0;
	firstIndexToInsertTo = 0;
	maximumCapacity = 8;
	guests = new Guest[8];
	enlargeTo = 8;
}
//Destructor - erases the allocated Guests's array
Restaurant::~Restaurant(){
delete[] guests;
}

//Copy Constructor
Restaurant::Restaurant(const Restaurant & r){
	int size;
	//Computing the needed number of cells in the Guests array, the number should be a multiple of 8
	if ((r.numOfGuests)%this->enlargeTo==0) 
		size = r.numOfGuests;
	else 
		size= r.numOfGuests - ((r.numOfGuests) % this->enlargeTo) + this->enlargeTo;
	//Allocating the array accordingly
	guests = new Guest[size]; 
	for(int j=0;j<size;j++) {
		guests[j] = r.guests[j];
	}
}
	

//Assignment operator
const Restaurant& Restaurant::operator=(const Restaurant& r) {
int size;
if (this!=&r){
	//Computing the needed number of cells in the Guests array, the number should be a multiple of 8
	if ((r.numOfGuests)%8==0) 
		size = r.numOfGuests;
	else 
		size= r.numOfGuests - ((r.numOfGuests)%8)  +8;
	//Allocating the array accordingly
	guests = new Guest[size]; 
	for(int j=0;j<size;j++) {
		guests[j] = r.guests[j];
	}
}
return *this;
}


/* This fuction checks the existence of a specific guest according to his unique guest number*/  
const bool Restaurant::checkGuestExistence(const int id) {
	for(int i=0;i<numOfGuests;i++){
		if (guests[i].getGuestNum() == id)
			return true;
	}
	return false;
}

/* This fuction checks the existence of an order for a  specific guest according to his unique guest number*/  
const bool Restaurant::checkOrderExistence(const int id) {
	if (checkGuestExistence(id))
		return guests[getGuestByNumber(id)].getHasOrder();
	else return false;
	
	/*int guestLoc = getGuestByNumber(id);
	if(guestLoc == -1){
		cout << "Guest number: " << id << " does not exist" <<endl; 
		return false;
	}
	else return guests[guestLoc].getHasOrder();*/
}
//return guest index in the array  if found or -1 else
const int  Restaurant::getGuestByNumber(const int guestNum) const  {
	for(int i=0;i<numOfGuests;i++){
		if (guests[i].getGuestNum() == guestNum)
			return i;
	}
	return -1;
}



/* This fuction expands the guests array and copies the old guests to the new array 
and deletes the old array*/  
const void Restaurant::copyAndEnlarge(int enlarge, int sizeOfPreviousArray) { 

//Extending the array
	
	Guest* newArr = new Guest[enlarge];
	maximumCapacity =enlarge;

	
//Copying previous array
	for (int j=0; j<sizeOfPreviousArray;j++) { 
		//Changed the Guest.operator= to suit our needs
		newArr[j] =guests[j];
	}
	delete[] (guests);
	guests= newArr;
	cout<<"Guests database successfuly expanded\n\n";
}
//This function adds an order to an existing 
const void Restaurant::addOrder(const int id,const string des,const string mc,const string fc, const string bev) { 
	int guestLoc =getGuestByNumber(id);
	if (guestLoc==-1) {
		cout<<"Guest number: "<<id<<" does not exist"<<endl;
		return;
	}
	else if (guests[guestLoc].getHasOrder()) {
		cout<<"Guest number: "<<id<<" already has an order"<<endl;
		return;
	}
	else {
		
		guests[guestLoc].setBeverage(bev);
		guests[guestLoc].setMainCourse(mc);
		guests[guestLoc].setFirstCourse(fc);
		guests[guestLoc].setDesert(des);
		guests[guestLoc].setOrderBool(true);
	}
	cout<<"Order for guest number: "<<id<< " has been addded"<<endl; 

}
/* This fuction adds a new guest to the  the guests array and expands the array if needed */  
const void Restaurant::addGuest(const string des,const string mc,const string fc, const string bev,const bool hasord) { 	
		//If the array is already full
		if (firstIndexToInsertTo>maximumCapacity-1){
			copyAndEnlarge(numOfGuests+this->enlargeTo,numOfGuests);
		}
		//call our onstuctor to create a new guest with the right parameters
		guests[firstIndexToInsertTo] = Guest(fc,mc,des,bev);
		guests[firstIndexToInsertTo].setOrderBool(hasord);
		numOfGuests++;
		firstIndexToInsertTo++;	
		cout<<"Guest successfuly added to the restaurant orders system\n\nGuest number is "<<guests[firstIndexToInsertTo-1].getGuestNum()<<"\n\n";
}

/* This fuction prints the courses of a specific guest according to his unique guest number*/  
const void Restaurant::getGuest(const int id,const int whatToGet){
		int index = getGuestByNumber(id);
	if (index==-1) { 
		cout<<"Guest number "<<id<<" does not exist and could not be set "<<endl;
		return;
	}
	else if (!guests[index].getHasOrder())
	{
		cout<<"Guest number "<<id<<" does not have an order yet"<<endl;
		return;
	}
	else
		{
			/*0-first course,1-main course,2-desert,3-beverage*/
		switch(whatToGet) { 
		case 0: {
			cout<<"First course for guest number "<<id<<" is: "<<"\"" <<guests[index].getFirstCourse()<<"\""<<"\n\n";
			break;
				}
		case 1: { 
				cout<<"Main course for guest number "<<id<<" is: "<<"\"" <<guests[index].getMainCourse()<<"\""<<"\n\n";
				break;
				}
		case 2: {
			cout<<"Desert for guest number "<<id<<" is: " <<"\""<<guests[index].getDesert()<<"\""<<"\n\n";
			break;
				}
		case 3: {
			cout<<"Beverage for guest number "<<id<<" is: " <<"\""<<guests[index].getBeverage()<<"\""<<"\n\n";
			break;
				}
		}
	}
}

/* This fuction sets the courses of a specific guest according to his unique guest number*/ 
const void Restaurant::setGuest(const int id,const string setString,const int whatToSet){
	int index = getGuestByNumber(id);
	if (index==-1) {
		cout<<"Guest number "<<id<<" does not exist and could not be set "<<endl;
		return;
	}
	else if (!guests[index].getHasOrder())
	{
		cout<<"Guest number "<<id<<" does not have an order yet"<<endl;
		return;
	}
	else {
		/*0-first course,1-main course,2-desert,3-beverage*/
		switch(whatToSet) { 
		case 0: {
			guests[index].setFirstCourse(setString);
			cout<<"First course for guest number "<<id<<" is now " <<"\""<<guests[index].getFirstCourse()<<"\""<<"\n\n";
			break;
				}
		case 1: { 
				guests[index].setMainCourse(setString);
				cout<<"Main course for guest number "<<id<<" is now " <<"\""<<guests[index].getMainCourse()<<"\""<<"\n\n";
				break;
				}
		case 2: {
			guests[index].setDesert(setString);
			cout<<"Desert for guest number "<<id<<" is now " <<"\""<<guests[index].getDesert()<<"\""<<"\n\n";
			break;
				}
		case 3: {
			guests[index].setBeverage(setString);
			cout<<"Beverage for guest number "<<id<<" is now " <<"\""<<guests[index].getBeverage()<<"\""<<"\n\n";
			break;
				}
		}
	}

}

/* This fuction removes the specified order from specified guest  */ 
const void Restaurant::removeOrder(const int guestId)
{
	int guestLoc = getGuestByNumber(guestId);
	
	if(guestLoc == -1){
		cout << "Guest number: " << guestId << " does not exist" <<endl;
	} else if (checkOrderExistence(guestId)){
		guests[guestLoc].setOrderBool(false);
		guests[guestLoc].setFirstCourse("");
		guests[guestLoc].setMainCourse("");
		guests[guestLoc].setBeverage("");
		guests[guestLoc].setDesert("");
		cout << "Order for guest " << guestId << " successfully removed" << endl;
	}
	else 
		cout << "Order for guest " << guestId << " does not exist" << endl;
}



/* This fuction removes the specified guest and calls another function that will preform 
the left shift in the array */ 
const void Restaurant::removeGuest(const int id){
	int index = getGuestByNumber(id);
	if (index==-1)
		cout<<"Guest number "<<id<<" does not exist \n\n";
	else {
		//The guest is in the restaurant
		this->removeGuestAndReorder(index);
		if (firstIndexToInsertTo>0)
			firstIndexToInsertTo--;
		else firstIndexToInsertTo = 0;
		if (numOfGuests>0)
		numOfGuests--;
		else numOfGuests = 0;
		
		cout<<"Guest number "<<id<<" successfuly removed from the restaurant orders system\n\n";
	}
}

/* This fuction performs the left shift in the array to avoid any "holes"*/  
const void Restaurant::removeGuestAndReorder(const int indexToRemove) { 
	for (int k=indexToRemove;k<numOfGuests-1;k++){
				guests[k] = guests[k+1];
	}
	//fill the last cell with an meaning-less data
	Guest g;
	guests[numOfGuests-1] =g; 
}
	







    


